﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Collections;

namespace AutoResumeSend.Componments
{




    /// <summary>
    /// 提供对http请求的访问封装

    /// </summary>
    public abstract class BaseHttpVisitor
    {

        private static Regex charsetRegex = new Regex(@".*charset\\s*=\\s*(.*?)", RegexOptions.IgnoreCase);
        private static readonly Encoding DEFAULT_ENCODING = Encoding.UTF8;


        public static BaseHttpVisitor NewHttpDirectVisitor()
        {
            return new HttpDirectVisitor();
        }


        internal BaseHttpVisitor() { }

        /// <summary>
        /// 读取url的数据内容到指定的流中,并可以使用callback参与到读取过程,但只应该在callback中使用

        /// HttpWebResponse的只读数据，比如head,万不可参与到流数据读取

        /// </summary>
        /// <param name="url">目标地址</param>
        /// <param name="to">把url的数据写入到此流</param>
        /// <param name="responseCallback">回调, 可为null</param>
        public abstract void ReadToStream(string url, Stream to, Action<HttpWebResponse> responseCallback);


        /// <summary>
        /// 读取url内容写入指定的流中,主要用于读取字节型数据，比如图片
        /// </summary>
        /// <param name="url"></param>
        /// <param name="to"></param>
        public void ReadToStream(string url, Stream to)
        {
            ReadToStream(url, to, null);
        }

        /// <summary>
        /// 读取url文本型内容,文本内容编码按HttpWebResponse对象的CharacterSet属性设置,
        /// 若对方站点并未设置CharacterSet，就使用默认UTF8编码读取,
        /// 若乱码请使用ReadUrl(string remoteUrl, Encoding forceEncoding)方法手工指定编码。

        /// </summary>
        /// <param name="remoteUrl">地址</param>
        /// <returns></returns>
        public string ReadUrl(string remoteUrl)
        {
            return ReadUrl(remoteUrl, null);
        }

        /// <summary>
        /// 读取url文本型内容

        /// 
        /// 虽然http头中可能包含编码值

        /// 但由于某些站点不按常理出牌(比如51job),遇到乱码使用此方法手工指定CharacterSet
        /// </summary>
        /// <param name="remoteUrl">地址</param>
        /// <param name="forceEncoding">用此编码读取数据，忽略HttpWebResponse的CharacterSet,
        /// 若为null则等同于ReadUrl(string remoteUrl)方法 </param>
        /// <returns></returns>
        public string ReadUrl(string remoteUrl, Encoding forceEncoding)
        {

            Encoding encoding = null;
            try
            {
                using (MemoryStream m = new MemoryStream())
                {
                    ReadToStream(remoteUrl, m, delegate(HttpWebResponse response)
                    {
                        //
                        encoding = forceEncoding ?? GetEncoding(response);
                    });

                    m.Position = 0;//内存流复位以便于重新读取

                    using (System.IO.StreamReader reader = new StreamReader(m, encoding))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
            catch(Exception ex)
            {
                LogHelper.LogError("读取网站内容出现异常" + ex.ToString());
                ex = null;
                return string.Empty;
            }
        }

        private Encoding GetEncoding(HttpWebResponse response)
        {

            Encoding encoding = DEFAULT_ENCODING;
            if (response.CharacterSet != null)
            {
                try
                {
                    encoding = Encoding.GetEncoding(response.CharacterSet);
                }
                catch (ArgumentException e)
                {
                    //ignore , return default encoding
                    Console.WriteLine(e.ToString());
                }
            }
            return encoding;
        }
    }



    /// <summary>
    /// 直接访问http网络
    /// </summary>
    internal class HttpDirectVisitor : BaseHttpVisitor
    {
        private const int TIME_OUT = 600000;

        public ArrayList ListMenu = new ArrayList();
        public List<string> menuList = new List<string>();
        public ArrayList BookThreadList = new ArrayList();
        public string ThreadCommentList = "";

        public override void ReadToStream(string url, Stream to, Action<HttpWebResponse> responseCallback)
        {
            System.Net.HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Timeout = TIME_OUT;
            request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5 (.NET CLR";
            request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
            request.Headers["Accept-Language"] = "en-us,en;q=0.5";
            request.Headers["Accept-Charset"] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7";

            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                if (responseCallback != null)
                {
                    responseCallback(response);
                }

                Stream outStream = response.GetResponseStream();

                byte[] buffer = new byte[100000];
                int count = 0;
                while ((count = outStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    to.Write(buffer, 0, count);
                }
            }
        }

        public string GetHtmlText(Stream to)
        {
            StreamReader sr = new StreamReader(to, System.Text.Encoding.UTF8);
            string strHtmlText = sr.ReadToEnd();
            to.Dispose();
            sr.Dispose();
            return strHtmlText;
        }



        public void getLinks(string m_html)
        {
            string regexStr = "<td width=[\'\"\"s]20%[\'\"\"s]><a[^<>]*?hrefs*=s*[\'\"\"s]([^\"\"']*)[\'\"\"][^<>]*?>(.*?)</a></td>";
            Match ma = Regex.Match(m_html, regexStr, RegexOptions.IgnoreCase);

            while (ma.Success)
            {
                try
                {
                    //Groups["href"].Value + "  " + ma.Groups["name"].Value;
                    ListMenu.Add(new string[] { ma.Groups[1].Value, ma.Groups[2].Value });

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                ma = ma.NextMatch();

            }
        }

       


      


        /// <summary>
        /// 按指定Encoding方式取得字符串的字节数
        /// </summary>
        /// <param name="strOri">字符串</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>字节数量</returns>
        public int GetBytesLength(string strOri, Encoding encoding)
        {
            int nRet = 0;

            if (strOri == null || strOri.Length == 0)
            {
                nRet = 0;
            }
            else
            {

                byte[] b_array = encoding.GetBytes(strOri);
                nRet = b_array.Length;
            }

            return nRet;
        }


        /// <summary>
        /// 过滤特殊html标记
        /// </summary>
        /// <param name="text"></param>
        /// <param name="maxGB2312Len"></param>
        private string FilterSring(string text, int maxGB2312Len)
        {
            string[] htmlArray =
                new string[] { "font", "div", "span", "strike", "strong", "marquee", "sub", "sup", "object", "table", "tr", "td", "tbody", "font", "img", "ol", "li", "br", "a", "u", "p", "b", "i", "embed", "parma" };
            if (string.IsNullOrEmpty(text))
                return string.Empty;

            text = Regex.Replace(text, "\r\n", "", RegexOptions.IgnoreCase);
            foreach (string htmlTag in htmlArray)
            {
                text = Regex.Replace(text, "</" + htmlTag + ">", "", RegexOptions.IgnoreCase);
            }

            int currentTagIndex = 0;
            int nextIndex = 0;
            foreach (string htmlTag in htmlArray)
            {
                nextIndex = 0;
                for (; Regex.IsMatch(text, "<" + htmlTag, RegexOptions.IgnoreCase); )
                {
                    currentTagIndex = text.IndexOf("<" + htmlTag, StringComparison.CurrentCultureIgnoreCase);

                    if (currentTagIndex >= 0)
                    {
                        //需要作过滤
                        nextIndex = text.IndexOf(">", currentTagIndex, StringComparison.CurrentCultureIgnoreCase);
                        text = text.Substring(0, currentTagIndex) + text.Substring(nextIndex + 1);
                    }
                    else
                    {
                        break;
                    }
                }
            }


            text = Regex.Replace(text, @"\[.*?\]", "", RegexOptions.IgnoreCase);
            text = Regex.Replace(text, @"\<.*?\>", "", RegexOptions.IgnoreCase);
            text = Regex.Replace(text, @"[0-9a-z]([a-z0-9\-]*[a-z0-9])?\.(com|net|org|cn|name|info|me|us|hk|tw|biz|cc|tv)", "", RegexOptions.IgnoreCase);



            return text;

        }


        /// <summary>
        /// 过滤特殊字符
        /// </summary>
        /// <param name="html"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        private string RegSubHtm(string html, int length)
        {
            string subHtml = string.Empty;
            if (string.IsNullOrEmpty(html))
                return string.Empty;

            if (html.Length >= length)
                subHtml = html.Substring(0, length);
            else
                subHtml = html;
            //  MessageBox.Show("subHtml:" + subHtml);

            bool isTagOpen = false;
            char[] charArray = subHtml.ToCharArray();
            Array.Reverse(charArray);

            foreach (char c in charArray)
            {
                if (c == '<')
                {
                    isTagOpen = true;
                    break;
                }

                if (c == '>')
                {
                    isTagOpen = false; break;
                }
            }

            if (isTagOpen)
            {
                string rightStr = html.Substring(length);
                int idxTagEnd = rightStr.IndexOf(">");
                subHtml += rightStr.Substring(0, idxTagEnd + 1);
            }

            Stack<string> stack = new Stack<string>();
            Regex reg = new Regex(@"(<.[^>]*>)|(<\/.[^>]*>)|<br/>|<br>|<hr>|<hr/>", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);

            MatchCollection mc = reg.Matches(subHtml);
            foreach (Match item in mc)
            {
                string toLowerItem = item.ToString().ToLower().Replace(" ", "");
                if (toLowerItem == "<br>" || toLowerItem == "<br/>" || toLowerItem == "<hr>" || toLowerItem == "<hr/>")
                    continue;

                if (item.ToString().StartsWith("</"))
                {
                    if (stack.Count > 0 && stack.Peek().Replace("<", "</") == item.ToString())
                        stack.Pop();
                }
                else
                {
                    stack.Push(GetBeginTag(item.ToString()));
                }
            }

            while (true)
            {
                if (stack.Count > 0)
                {
                    subHtml += stack.Pop().Replace("<", "</");
                }
                else
                {
                    break;
                }
            }
            subHtml = FilterSring(subHtml, length);
            return subHtml;

        }

        private string GetBeginTag(string input)
        {
            int idx = input.IndexOf(" ");
            if (idx > 0)
            {
                return input.Substring(0, idx) + ">";
            }
            else
            {
                return input;
            }
        }



    }
}
